package com.zmj.mobile.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zmj.amc.sdk.entity.User;
import com.zmj.framework.base.service.impl.BaseServiceImpl;
import com.zmj.framework.exception.CustomException;
import com.zmj.framework.response.ResponseCode;
import com.zmj.framework.response.Result;
import com.zmj.framework.util.PageUtil;
import com.zmj.framework.util.ThreadContextHandler;
import com.zmj.mobile.dto.AuditDTO;
import com.zmj.mobile.dto.TechPurDetailBaseDTO;
import com.zmj.mobile.dto.TechPurDetailInsertDTO;
import com.zmj.mobile.dto.TechPurDetailUpdateDTO;
import com.zmj.mobile.dto.TechPurMainBaseDTO;
import com.zmj.mobile.dto.TechPurMainIdDTO;
import com.zmj.mobile.dto.TechPurMainInsertDTO;
import com.zmj.mobile.dto.TechPurMainPageDTO;
import com.zmj.mobile.dto.TechPurMainUpdateDTO;
import com.zmj.mobile.entity.OrgEntity;
import com.zmj.mobile.entity.TechPurDetailEntity;
import com.zmj.mobile.entity.TechPurMainEntity;
import com.zmj.mobile.enums.ExceptionEnum;
import com.zmj.mobile.mapper.ITechPurMainMapper;
import com.zmj.mobile.mapstruct.TechPurDetailMapStruct;
import com.zmj.mobile.mapstruct.TechPurMainMapStruct;
import com.zmj.mobile.process.AuditServiceEnum;
import com.zmj.mobile.process.AuditServiceFactory;
import com.zmj.mobile.process.IAuditService;
import com.zmj.mobile.service.IOrgService;
import com.zmj.mobile.service.ITechPurDetailService;
import com.zmj.mobile.service.ITechPurMainService;
import com.zmj.mobile.vo.TechPurMainIdVO;
import com.zmj.mobile.vo.TechPurMainVO;
import com.zmj.modules.flow.entity.dto.BpmTaskCcQueryDto;
import com.zmj.modules.flow.entity.vo.TodoTaskVO;
import com.zmj.modules.flow.service.FlowableService;
import lombok.SneakyThrows;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;


/**
 * <p>
 * 研发试制/采购申请表 服务实现类
 * </p>
 *
 * @author lzy
 * @since 2024-02-01
 */
@Service
public class TechPurMainServiceImpl extends BaseServiceImpl<ITechPurMainMapper, TechPurMainEntity> implements ITechPurMainService {
    @Resource
    private ITechPurMainMapper techPurMainMapper;
    @Resource
    private ITechPurDetailService techPurDetailService;
    @Resource
    private AuditServiceFactory auditServiceFactory;

    @Resource
    private IOrgService iOrgService;
    @Resource
    private FlowableService flowableService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TechPurMainIdVO insert(TechPurMainInsertDTO insertDTO) {
        User user = new User();
        user.setUsername(insertDTO.getCreateUser());
        user.setRealName(insertDTO.getCreateUserName());
        ThreadContextHandler.setCurrentUser(user);

        Optional<OrgEntity> orgEntityOptional = iOrgService.getByUserName(insertDTO.getCreateUser());
        if (orgEntityOptional.isPresent()) {
            insertDTO.setDepartCode(orgEntityOptional.get().getOrgCode());
            insertDTO.setDepartName(orgEntityOptional.get().getOrgName());
        }

        TechPurMainEntity entity = TechPurMainMapStruct.INSTANCE.toTechPurMain(insertDTO);

        techPurMainMapper.insert(entity);
        Long techPurId = entity.getId();
        //保存明细
        saveDetailList(insertDTO, techPurId, true);

        IAuditService auditService = auditServiceFactory.getAuditService(AuditServiceEnum.getExample(AuditServiceEnum.TECH_PUR_MAIN.getCode()));
        auditService.agree(AuditDTO.builder().id(techPurId).build());
        return TechPurMainIdVO.builder().id(techPurId).build();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateById(TechPurMainUpdateDTO updateDTO) {
        TechPurMainEntity entity = TechPurMainMapStruct.INSTANCE.toTechPurMain(updateDTO);
        techPurMainMapper.updateById(entity);
        //保存明细
        saveDetailList(updateDTO, entity.getId(), false);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(TechPurMainIdDTO idDTO) {
        techPurMainMapper.deleteById(TechPurMainEntity.builder().id(idDTO.getId()).build());
    }

    @Override
    public TechPurMainVO getById(TechPurMainIdDTO idDTO) {
        Long id = idDTO.getId();
        TechPurMainEntity entity = checkExists(id);
        TechPurMainVO techPurMainVO = TechPurMainMapStruct.INSTANCE.toTechPurMainVO(entity);

        LambdaQueryWrapper<TechPurDetailEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(TechPurDetailEntity::getTechPurId, id);
        List<TechPurDetailEntity> list = techPurDetailService.list(queryWrapper);
        list = list == null ? new ArrayList<>() : list;
        techPurMainVO.setDetailList(list);

        //查询待办
        String flowId = entity.getFlowId();
        if (StringUtils.isEmpty(flowId)) {
            return techPurMainVO;
        }
        BpmTaskCcQueryDto bpmQueryDto = new BpmTaskCcQueryDto();
        bpmQueryDto.setProcInstId(flowId);
        bpmQueryDto.setSize(5);
        Result<Map<String, Object>> allTodoTasks = flowableService.getAllTodoTasks(bpmQueryDto);
        Map<String, Object> dataMap = allTodoTasks.getData();
        if (dataMap == null) {
            throw new CustomException(ExceptionEnum.GET_TASK_INFO_FAIL);
        }
        Page<Map<String, Object>> data = BeanUtil.fillBeanWithMap(dataMap, new Page<>(), false);
        List<Map<String, Object>> records = data.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            techPurMainVO.setTaskId("");
            return techPurMainVO;
        }
        //if (records.size() > 1) {
        //    //log.warn("业务id#{}#工作流id#{}#询价审批待办任务不唯一！", id, flowId);
        //}
        Map<String, Object> recordMap = records.get(0);
        TodoTaskVO todoTaskVO = BeanUtil.fillBeanWithMap(recordMap, new TodoTaskVO(), false);
        techPurMainVO.setTaskId(todoTaskVO.getTaskId());
        return techPurMainVO;
    }

    @Override
    public IPage<TechPurMainVO> pageList(TechPurMainPageDTO pageDTO) {
        LambdaQueryWrapper<TechPurMainEntity> queryWrapper = Wrappers.lambdaQuery();
        IPage<TechPurMainEntity> page = techPurMainMapper.selectPage(PageUtil.buildPage(pageDTO), queryWrapper);

        return TechPurMainMapStruct.INSTANCE.convertPage(page);
    }

    private void saveDetailList(TechPurMainBaseDTO baseDTO, Long techPurId, boolean insertFlag) {
        List<? extends TechPurDetailBaseDTO> detailList = insertFlag ? ((TechPurMainInsertDTO) baseDTO).getDetailList() : ((TechPurMainUpdateDTO) baseDTO).getDetailList();
        if (CollectionUtils.isNotEmpty(detailList)) {
            List<TechPurDetailEntity> targetList = new ArrayList<>();
            detailList.forEach(item -> {
                TechPurDetailEntity entity = insertFlag ? TechPurDetailMapStruct.INSTANCE.toTechPurDetail((TechPurDetailInsertDTO) item) : TechPurDetailMapStruct.INSTANCE.toTechPurDetail((TechPurDetailUpdateDTO) item);
                entity.setTechPurId(techPurId);
                targetList.add(entity);
            });
            if (insertFlag) {
                techPurDetailService.saveBatch(targetList);
            } else {
                techPurDetailService.saveOrUpdateBatch(targetList);
            }
        }
    }

    private TechPurMainEntity checkExists(Long id) {
        TechPurMainEntity entity = techPurMainMapper.selectById(id);
        if (entity == null) {
            throw new CustomException(ExceptionEnum.TECH_PUR_MAIN_NOT_EXISTS);
        }
        return entity;
    }

    /**
     * @Description 导入研发试制主表
     * @Author songxin
     * @Date 18:18 2024/2/1 0001
     **/
    @SneakyThrows
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public void importExcel(MultipartFile file) {

        //加载excel文件
        List<TechPurMainBaseDTO> TechPurMainBaseDTOS = EasyExcel.read(file.getInputStream()).excelType(ExcelTypeEnum.XLSX)
                .extraRead(CellExtraTypeEnum.HYPERLINK).extraRead(CellExtraTypeEnum.HYPERLINK)
                .head(TechPurMainBaseDTO.class)
                .sheet()
                .doReadSync();
        if (CollectionUtil.isEmpty(TechPurMainBaseDTOS)) {
            throw new CustomException(ResponseCode.INTERNAL_SERVER_ERROR.getCode());
        }
        //
        List<TechPurMainEntity> techPurMainEntityList = new ArrayList<>();
        for (TechPurMainBaseDTO TechPurMainBaseDTO : TechPurMainBaseDTOS) {
            TechPurMainEntity techPurMainEntity = new TechPurMainEntity();
            BeanUtil.copyProperties(TechPurMainBaseDTO, techPurMainEntity);
            //quoteItemDetailEntity.setQuoteItemId(System.currentTimeMillis());
            techPurMainEntityList.add(techPurMainEntity);
        }
        this.saveBatch(techPurMainEntityList.stream().distinct().collect(Collectors.toList()));
    }
}
